package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	//"strconv"
	"io/ioutil"
)

//Dir 程序执行目录，与升级文件存放位置有关
const Dir string = "."

//返回wifi列表的结构体

type aplist struct {
	SSID     string `json:"ssid"`
	CHAN     string `json:"channel"`
	RATE     string `json:"rate"`
	SIGNAL   string `json:"signal"`
	SECURITY string `json:"security"`
}
type videocoding struct {
	RESOLUTION string `json:"resolution"`
}

var cmdPush = exec.Command("/bin/bash", "-c", "ls") //只是用来定义一个全局cmd



func main() {
	log.Println("我是你儿！！！")
	r := gin.Default()
	r.GET("/:query", deal)
	r.POST("/on_play_auth", postDeal)
	r.Run() // listen and serve on 0.0.0.0:8080
}

//用来处理视频拉流鉴权的请求
// ffplay -fflags nobuffer rtmp:192.168.31.221/hls/video?password=123456   在视频拉取时写入
func postDeal(c *gin.Context) {
	password := c.PostForm("password")
	//首先要去读取文件中设置的密码是多少，然后进行比较
	oriPassword := filecontent("../projectconfig/authority.txt", "password", "", 0)
	log.Println(oriPassword)
	if password == oriPassword {
		log.Println("jianquanlaile\r\n")
		c.String(200, "post")
	} else {
		log.Println("password error\r\n")
		c.String(404, "post")
	}
}

//处理http请求
//TODO: 需要返回给请求端一定的数据，待整理
func deal(c *gin.Context) {
	query := c.Param("query")
	if query == "getaplist" {
		c.String(200, getaplist())
	} else if query == "setapcli" {
		ssid := c.DefaultQuery("ssid", "")
		password := c.DefaultQuery("password", "")
		resp := setapcli(ssid, password)
		c.String(200, resp)
	} else if query == "getvideocoding" {
		c.String(200, getvideocoding())
	} else if query == "setResolution" {
		log.Println("ahhhhhhh\n")
		resolution := c.DefaultQuery("resolution", "")
		c.String(200, setResolution(resolution))
	} else if query == "update" {
		url := c.DefaultQuery("url", "")
		c.String(200, update(url))
	} else if query == "setauthority" {
		password := c.DefaultQuery("password", "")
		c.String(200, setauthority(password))

	}
}

//封装一个函数，用来查找、替换指定文件的某一行的参数值
//第一个参数是指定的文件的名称;第二个参数是需要修改的文件中的行的key;第三个参数是是需要修改的value值;第四个参数值是用来指定是修改参数还是查询参数，1表示修改，0表示查询
func filecontent(filename string, linekey string, param string, flag int) string {
	var returnStr string
	input, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Println(err)
	}
	lines := strings.Split(string(input), "\n")
	for i, line := range lines { //筛选每一行
		lineStringArray := strings.Split(line, ":")
		linestringkey := string(lineStringArray[0])
		if linestringkey == linekey { //寻找到对应的行
			fmt.Printf(line + "\n")
			if flag == 1 {
				lines[i] = linestringkey + ":" + param
				output := strings.Join(lines, "\n")
				err = ioutil.WriteFile(filename, []byte(output), 0644)
				if err != nil {
					log.Println(err)
				}
				returnStr = "set ok"
				break
			} else {
				returnStr = lineStringArray[1]
				break
			}
		}
	}
	return returnStr
}

//用来设置推流鉴权的密码
//http://192.168.31.221:8080/setauthority?password=123456
func setauthority(password string) string {
	//打开文件，将密码修改进去
	return filecontent("../projectconfig/authority.txt", "password", password, 1)
}

//获取摄像头的参数，现在只返回了分辨率这一个参数

func getvideocoding() string {
	command := `echo "123" | sudo -S v4l2-ctl --list-framesizes=MJPG -d /dev/video10 | awk -F " " '{print $3}'`
	cmd := exec.Command("/bin/bash", "-c", command)
	bytes, err := cmd.Output()
	if err != nil {
		log.Println(err)
	}
	log.Println(bytes)
	pixTemp := strings.Replace(string(bytes), "\n", ",", -1)
	pixTemp = strings.TrimRight(pixTemp, ",")
	pixTemp = strings.TrimLeft(pixTemp, ",")
	var VDjson videocoding
	VDjson.RESOLUTION = pixTemp
	json, err := json.Marshal(VDjson) //生成json
	fmt.Println(string(json))
	return string(json)
}

//设置推流视频的分辨率
func pushStream(com string) {

	cmdPush = exec.Command("/bin/bash", "-c", com)
	cmdPush.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	cmdPush.Run()
}
func pushStream_ffmpeg() {
	cmd_push_ffmpeg := exec.Command("/bin/bash", "-c", "ffmpeg -re -i /home/orangepi/test.264 -codec copy -f rtsp -rtsp_transport tcp rtsp://192.168.31.221:554")//只是用来定义一个全局cmd
	cmd_push_ffmpeg.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	cmd_push_ffmpeg.Run()
	log.Println("ffmpeg run\n")
}
func setResolution(resolution string) string {
	
	fmt.Println("come\n")

	resolutionArray := strings.Split(resolution, "x")
	width := string(resolutionArray[0])
	height := string(resolutionArray[1])

	command := `ps -e | grep "gst-launch-1.0"| awk '{print $1}'`
	cmd := exec.Command("/bin/bash", "-c", command)
	bytes, err := cmd.Output()
	if err != nil {
		log.Println(err)
	} else {
		pid := string(bytes)
		log.Println(pid)
		if pid != "" {
			syscall.Kill(-cmdPush.Process.Pid, syscall.SIGKILL)
		}
	}
	command = "gst-launch-1.0 v4l2src device=/dev/video10 ! \"image/jpeg,width="+width+",height="+height+"\" ! jpegdec ! videoconvert ! queue ! mpph264enc ! filesink location=/home/orangepi/test.264"
	
	fmt.Println(command)
	go pushStream(command)
	go pushStream_ffmpeg()
	return "set_resolution ok"
}

//nmcli -m tabular -t -f SSID,CHAN,RATE,SIGNAL,SECURITY d wifi list ifname wlp1s0 | awk -F: '{for(i=1;i<=NF;++i) print $i}'
//http://192.168.31.132:8080/getaplist
func getaplist() string {
	rescan()
	command := `nmcli -m tabular -t -f SSID,CHAN,RATE,SIGNAL,SECURITY d wifi list ifname wlp1s0 | awk -F: '{for(i=1;i<=NF;++i) print $i}'`
	cmd := exec.Command("/bin/bash", "-c", command)
	bytes, err := cmd.StdoutPipe()
	if err != nil {
		log.Println(err)
	}
	cmd.Start()

	reader := bufio.NewReader(bytes)

	allAPjson := []aplist{} //结构体数组，用于生成json
	var APjson aplist       //结构体用于保存每一个wifi信息
	//实时循环读取输出流中的一行内容
	var line []byte
	for {
		line, _, err = reader.ReadLine()
		if err != nil || io.EOF == err {
			fmt.Println("EOF1")
			break
		}
		ssid := string(line) //读取ssid
		APjson.SSID = ssid
		line, _, err = reader.ReadLine()
		if err != nil || io.EOF == err {
			fmt.Println("EOF2")
			break
		}
		channel := string(line) //wifi信道
		APjson.CHAN = channel
		line, _, err = reader.ReadLine()
		if err != nil || io.EOF == err {
			fmt.Println("EOF3")
			break
		}
		rate := string(line) //wifi速率
		APjson.RATE = rate
		line, _, err = reader.ReadLine()
		if err != nil || io.EOF == err {
			fmt.Println("EOF4")
			break
		}
		signal := string(line) //wifi信号强度
		APjson.SIGNAL = signal
		line, _, err = reader.ReadLine()
		if err != nil || io.EOF == err {
			fmt.Println("EOF5")
			break
		}
		security := string(line) //wifi认证方式
		APjson.SECURITY = security

		allAPjson = append(allAPjson, APjson)
	}
	json, err := json.Marshal(allAPjson) //生成json
	// fmt.Println(string(json))
	return string(json)
}

// sudo nmcli dev wifi connect iPhone password xch123456 ifname  wlp1s0
// http://192.168.31.132:8080/connect_wifi?ssid=iPhone&password=xch123456
func setapcli(ssid string, password string) string {
	discon()
	rescan()
	command := `echo "123" | sudo -S nmcli device wifi connect`
	command = command + " " + ssid + " " + "password" + " " + password + " " + "ifname  wlp1s0"

	cmd := exec.Command("/bin/bash", "-c", command)
	// fmt.Println(cmd)
	bytes, err := cmd.Output()
	if err != nil {
		log.Println(err)
	}
	resp := string(bytes)
	return resp
}

// http://192.168.31.240:8080/update?url=http://47.95.10.123:8080/bin_file/main
func update(url string) string {
	resp, err := http.Get(url)
	if err != nil {
		return err.Error()
	}
	defer resp.Body.Close()

	//对url切片，获取文件名
	// urlslice := strings.Split(url, "/")
	// filename := urlslice[len(urlslice)-1]
	// 创建一个文件用于保存
	out, err := os.Create(Dir + "/" + "tmp")
	if err != nil {
		return err.Error()
	}
	defer out.Close()

	// 然后将响应流和文件流对接起来
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return err.Error()
	}

	//覆盖原二进制文件
	command := `echo "123" | sudo -S mv tmp main`
	cmd := exec.Command("/bin/bash", "-c", command)
	// fmt.Println(cmd)
	err = cmd.Run() //阻塞
	if err != nil {
		return "Execute Command failed:" + err.Error()
	}

	command = `echo "123" | sudo -S chmod 775 main`
	cmd = exec.Command("/bin/bash", "-c", command)
	// fmt.Println(cmd)
	err = cmd.Run() //阻塞
	if err != nil {
		return "Execute Command failed:" + err.Error()
	}
	return "Download OK"
}

//重新扫描wifi，防止wifi列表只有一个已连接的wifi
func rescan() {
	command := `echo "123"|sudo -S nmcli d wifi rescan`
	cmd := exec.Command("/bin/bash", "-c", command)
	err := cmd.Run()
	if err != nil {
		log.Println(err)
	}
	time.Sleep(2 * time.Second)

}

func discon() {
	command := `echo "123"|sudo -S nmcli dev disconnect wlp1s0`
	cmd := exec.Command("/bin/bash", "-c", command)
	err := cmd.Run()
	if err != nil {
		log.Println(err)
	}
}

